package gates;

import register.Register;
import gates.FunctionGate;
import mathtools.Complex;
import java.util.Random;

/**
 * The measurement gate which measures the state of all the qubits in the register simultaneously.
 * It collapses the wavefunction and is an irreversible gate. 
 * @author Jan Zaucha
 *
 */
public class Measurement extends FunctionGate {

	/** Create a random number generator. 
	 * Need to store as we can seed the RNG
	 */
	private Random randomGenerator;

	/**
	 * Constructor (no specified seed)
	 */
	protected Measurement(){
		randomGenerator = new Random();
	}
	
	/**
	 * Constructor (specified seed)
	 * 
	 * @param seed
	 */
	public Measurement(long seed){
		randomGenerator = new Random(seed);
	}
	
	/**
	 * set the seed
	 * @param seed  
	 */
	public void setSeed(long seed){
		randomGenerator.setSeed(seed);
		
	}

	/**
	 * Returns the name of the gate regardless of representation.
	 */
	public String getName() {
		return "Measurement";
	}

	/**
	 * Measures the state of all the qubits simultaneously.
	 * note: this is an irreversible gate,
	 * the measurement collapses the wavefunction
	 * See interface <code>Gate</code> for usage.
	 * @param r the register 
	 */
	public void apply(Register r) {
		
		// prepare the array for the new register
		Complex [] newRegister = new Complex [r.getHeight()]; 
		for(int j=0; j<r.getHeight(); j++){
			newRegister[j] = new Complex(0.0f);
		}
		// first draw a random number between 0 (inclusive) and 1
		double random = Math.random();
		//check which state is the register in
		double currentPosition = 0.0; // this is the "position" along a normalized probability line 
		for(int i=0; i<r.getHeight(); i++){
			currentPosition += r.getElement(0, i).getMagnitudeSquared();
			if(random < currentPosition){
				// collapse the wavefunction
				newRegister[i]= new Complex(1.0f);
				r.update(newRegister);
				break;  // break loop so that register stays in this state
			}
		}


	}



}
